﻿using System.IO;
using System.Threading;
using Mitosoft.Definitions.Data;
using Mitosoft.Definitions.ViewModels;
using Mitosoft.TextFileReader;
using TextFileReaderModule.Interfaces;
using TextFileReaderModule.Services;
using TextFileReaderModule.ViewModels;

namespace TextFileReaderModule.Manager
{
  /// <summary>
  /// Manages the data of one file.
  /// </summary>
  public class OneFileDataManager : BaseViewModel
  {
    #region constants

    /// <summary>
    /// Size of cache used to store line positions.
    /// </summary>
    protected const uint LINE_POSITIONS_CACHE_SIZE = 1024;

    /// <summary>
    /// Size of cache used to store line contents.
    /// </summary>
    protected const uint LINE_CONTENT_CACHE_SIZE = 1024;

    #endregion

    #region delegates and events
    #endregion

    #region fields

    /// <summary>
    /// Provides text file data.
    /// </summary>
    protected TextFileReader _textFileReaderProvider;

    /// <summary>
    /// See <see cref="CachedBlockDataProvider{D,V}"/>
    /// </summary>
    protected CachedBlockDataProvider<IGenericDataBlockItem<string>, string> _cachedBlockDataProvider;

    /// <summary>
    /// Represents <see cref="LogFile"/>
    /// </summary>
    protected string _logFile;

    /// <summary>
    /// Represents the manager responsible to generate and to store the view model instances.
    /// </summary>
    protected readonly GenericDataBlockItemViewModelManager _genericDataBlockItemViewModelManager;

    /// <summary>
    /// Represents the service being able to store and to retrieve comments.
    /// </summary>
    protected readonly ICommentService _commentService = new CommentService();

    #endregion

    #region constructors

    /// <summary>
    /// Creates a <see cref="OneFileDataManager"/> instance.
    /// </summary>
    public OneFileDataManager()
    {
      _genericDataBlockItemViewModelManager = new GenericDataBlockItemViewModelManager(_commentService);
    }

    #endregion

    #region properties

    /// <summary>
    /// Provides cached data.
    /// Used by the view.
    /// </summary>
    // ReSharper disable UnusedMember.Global
    public CachedBlockDataProvider<IGenericDataBlockItem<string>, string> CachedBlockDataProvider
    // ReSharper restore UnusedMember.Global
    {
      get
      {
        return _cachedBlockDataProvider;
      }
      protected set
      {
        _cachedBlockDataProvider = value;
      }
    }

    /// <summary>
    /// Represents the path of the log file.
    /// </summary>
    public string LogFile
    {
      get { return _logFile; }
      set
      {
        _logFile = value;

        // Clear all comments assuming that the text file provider will change:
        // Same for the view model manager
        _commentService.Clear();
        _genericDataBlockItemViewModelManager.Clear();

        if (string.IsNullOrEmpty(value) || !File.Exists(value))
        {
          _textFileReaderProvider = null;

          if (CachedBlockDataProvider != null)
            CachedBlockDataProvider.DataBlockItemInstanceRequest -= OnNewTextFileReaderItemInstance;

          CachedBlockDataProvider = null;
        }
        else
        {
          _textFileReaderProvider = new TextFileReader(value, LINE_POSITIONS_CACHE_SIZE, LINE_CONTENT_CACHE_SIZE, 0);

          CachedBlockDataProvider = new CachedBlockDataProvider<IGenericDataBlockItem<string>, string>(
              _textFileReaderProvider, LINE_CONTENT_CACHE_SIZE, SynchronizationContext.Current);

          CachedBlockDataProvider.DataBlockItemInstanceRequest += OnNewTextFileReaderItemInstance;
        }

        HandlePropertyChanged();
        // ReSharper disable once ExplicitCallerInfoArgument
        HandlePropertyChanged("CachedBlockDataProvider");
      }
    }

    /// <summary>
    /// Represents the service handling comments for THIS file.
    /// </summary>
    public ICommentService CommentService
    {
      get { return _commentService; }
    }

    #endregion

    #region methods

    /// <summary>
    /// The text file reader returned a new instance which will be converted
    /// in a <see cref="GenericDataBlockItemViewModel"/> view model.
    /// </summary>
    /// <param name="datablockitem">Instance created from the text file reader.</param>
    /// <param name="sourceIndex">Represents the source index.</param>
    /// <returns>Converted view model.</returns>
    protected IGenericDataBlockItem<string> OnNewTextFileReaderItemInstance(
      IGenericDataBlockItem<string> datablockitem, int sourceIndex)
    {
      return
        _genericDataBlockItemViewModelManager.GetGenericDataBlockItemViewModel(datablockitem, sourceIndex);
    }

    /// <summary>
    /// Disposes this object.
    /// </summary>
    /// <param name="isDisposing">Represents whether this object is disposing.</param>
    protected override void Dispose(bool isDisposing)
    {
      if (_isDisposed) return;

      if (isDisposing)
      {
        #region dispose managed resources

        if (CachedBlockDataProvider != null)
          CachedBlockDataProvider.DataBlockItemInstanceRequest -= OnNewTextFileReaderItemInstance;

        #endregion
      }

      #region clean up unmanaged resources

      #endregion

      _isDisposed = true;
    }

    #endregion
  }
}
